/*
 *  Openmysee
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
				 
#include "echo.h"
void freeMedia (struct Channel *pc)
{
	int i;
	struct LiveChannelInfo *pcinfo = pc->pcinfo;
	if (pcinfo == NULL || pcinfo->media == NULL) return;
	for (i=0; i<pcinfo->cur_channel; i++)
	{
		free (pcinfo->media[i].data);
	}
	free (pc->pcinfo->media);
	pc->pcinfo->media = NULL;
	pc->pcinfo->cur_channel = 0;
}

#ifdef __CP_SOURCE
void addMedia (struct Channel *pc, int start, int len, int dlen, char *data, char *progname, char *channel_name)
#endif
#ifdef __SP_SOURCE
void addMedia (struct Channel *pc, int start, int len, int dlen, char *data, char *progname)
#endif
{
	struct LiveChannelInfo *pcinfo = pc->pcinfo;
	PDEBUG ("Add media to %p, %d, %d, %d\n", pc, start, len, dlen);
	if (pcinfo == NULL || pcinfo->media == NULL) return;
	if (pcinfo->cur_channel >= pcinfo->max_channel)
		return;
	pcinfo->media[pcinfo->cur_channel].start = start;
	pcinfo->media[pcinfo->cur_channel].len = len;
	pcinfo->media[pcinfo->cur_channel].dlen = dlen;
	strncpy (pcinfo->media[pcinfo->cur_channel].progname, progname, CHNLURL_LEN);
#ifdef __CP_SOURCE
	strncpy (pcinfo->media[pcinfo->cur_channel].channel_name, channel_name, CHNLURL_LEN);
#endif
	if (dlen > 0)
	{
		pcinfo->media[pcinfo->cur_channel].data = calloc (1, dlen);
		memcpy (pcinfo->media[pcinfo->cur_channel].data, data, dlen);
	} else
		pcinfo->media[pcinfo->cur_channel].data = NULL;
	pcinfo->cur_channel ++;
	PDEBUG ("Add media succeed.\n");
}

#ifdef __CP_SOURCE
int isHit (struct Channel *pc, int blockid)
{
	int i;
	struct LiveChannelInfo *pcinfo = pc->pcinfo;
	if (pcinfo == NULL || pcinfo->media == NULL || pcinfo->max_queue == 0) return -1;
	int realid = blockid % pcinfo->max_queue;
	for (i=0; i<pcinfo->cur_channel; i++)
	{
		if (realid == pcinfo->media[i].start)
			return i;
	}
	return -1;
}
#endif
static int transID (struct Channel *pc, int blockid)
{
	int i;
	struct LiveChannelInfo *pcinfo = pc->pcinfo;
	if (pcinfo == NULL || pcinfo->media == NULL || pcinfo->max_queue == 0) return -1;
	int realid = blockid % pcinfo->max_queue;
	for (i=0; i<pcinfo->cur_channel; i++)
	{
		if (realid < pcinfo->media[i].start)
			return i-1;
	}
	return (pcinfo->cur_channel -1);
}

void sendIdMedia (struct Session *p, struct Channel *pc, int id, int copymd5)
{
	int i, namelen;
	struct MediaData *media;
	char buffer[MAX_MSG_SIZE], *buf;
	PDEBUG ("send media to %p, %p, %d\n", p, pc, id);
	if (pc->pcinfo == NULL || (media = pc->pcinfo->media) == NULL
			|| (pc->type == T_PLIST && pc->pcinfo->max_queue == 0))
		return;
	buf = buffer +sizeof (int);
	*(unsigned char *)buf = P2P_MEDIATYPE;
	buf += sizeof (char);
	if (copymd5)
	{
		memcpy (buf, pc->channel_md5, MD5_LEN);
		buf += MD5_LEN;
	}
	if (pc->type == T_PLIST)
	{
		if ((i = transID (pc, id)) < 0) return;
		*(int *)buf = media[i].start + (id / pc->pcinfo->max_queue) * pc->pcinfo->max_queue;
	} else
	{
		i = 0;
		*(int *)buf = 0;
	}
	buf += sizeof (int);
	*(int *)buf = media[i].len;
	buf += sizeof (int);
	*(int *)buf = media[i].dlen;
	buf += sizeof (int);
	if (media[i].dlen > 0)
	{
		memcpy (buf, media[i].data, media[i].dlen);
		buf += media[i].dlen;
	}
	if (media[i].progname != NULL)
	{
		if ((namelen = strlen (media[i].progname)) >= CHNLURL_LEN)
			namelen = CHNLURL_LEN - 1;
		*(unsigned char *)buf = namelen+1;
		buf += sizeof (char);
		memcpy (buf, media[i].progname, namelen);
		buf[namelen] = 0;
		buf += namelen+1;
	} else
	{
		*(unsigned char *)buf = 1;
		buf += sizeof (char);
		*(unsigned char *)buf = 0;
		buf += sizeof (char);
	}
	*(unsigned int *)buf = 0;
	buf += sizeof (int);
#ifdef __SP_SOURCE
	if ((namelen = strlen (pc->channel_name)) >= CHNLURL_LEN)
		namelen = CHNLURL_LEN - 1;
	*(unsigned char *)buf = namelen;
	buf += sizeof (char);
	memcpy (buf, pc->channel_name, namelen);
	buf[namelen] = 0;
	buf += namelen+1;
#endif
#ifdef __CP_SOURCE
	if ((namelen = strlen (media[i].channel_name)) >= CHNLURL_LEN)
		namelen = CHNLURL_LEN - 1;
	*(unsigned char *)buf = namelen;
	buf += sizeof (char);
	memcpy (buf, media[i].channel_name, namelen);
	buf[namelen] = 0;
	buf += namelen+1;
#endif

	*(int *)buffer = buf - buffer;
	writeMessage (p, pc, buffer);
	PDEBUG ("send media succeed.\n");
}

void sendHitMedia (struct Session *p, struct Channel *pc, int i, int startid, int copymd5)
{
	struct MediaData *media;
	int namelen;
	char buffer[MAX_MSG_SIZE], *buf;
	if (pc->pcinfo == NULL || (media = pc->pcinfo->media) == NULL)
		return;
	PDEBUG ("send media to %p, %p, %d\n", p, pc, startid);
	buf = buffer +sizeof (int);
	*(unsigned char *)buf = P2P_MEDIATYPE;
	buf += sizeof (char);
	if (copymd5)
	{
		memcpy (buf, pc->channel_md5, MD5_LEN);
		buf += MD5_LEN;
	}
	*(int *)buf = startid;
	buf += sizeof (int);
	*(int *)buf = media[i].len;
	buf += sizeof (int);
	*(int *)buf = media[i].dlen;
	buf += sizeof (int);
	if (media[i].dlen > 0)
	{
		memcpy (buf, media[i].data, media[i].dlen);
		buf += media[i].dlen;
	}
	if (media[i].progname != NULL)
	{
		if ((namelen = strlen (media[i].progname)) >= CHNLURL_LEN)
			namelen = CHNLURL_LEN - 1;
		*(unsigned char *)buf = namelen+1;
		buf += sizeof (char);
		memcpy (buf, media[i].progname, namelen);
		buf[namelen] = 0;
		buf += namelen+1;
	} else
	{
		*(unsigned char *)buf = 1;
		buf += sizeof (char);
		*(unsigned char *)buf = 0;
		buf += sizeof (char);
	}
	*(unsigned int *)buf = 0;
	buf += sizeof (int);
#ifdef __SP_SOURCE
	if ((namelen = strlen (pc->channel_name)) >= CHNLURL_LEN)
		namelen = CHNLURL_LEN - 1;
	*(unsigned char *)buf = namelen;
	buf += sizeof (char);
	memcpy (buf, pc->channel_name, namelen);
	buf[namelen] = 0;
	buf += namelen+1;
#endif
#ifdef __CP_SOURCE
	if ((namelen = strlen (media[i].channel_name)) >= CHNLURL_LEN)
		namelen = CHNLURL_LEN - 1;
	*(unsigned char *)buf = namelen;
	buf += sizeof (char);
	memcpy (buf, media[i].channel_name, namelen);
	buf[namelen] = 0;
	buf += namelen+1;
#endif
	*(int *)buffer = buf - buffer;
	writeMessage (p, pc, buffer);
	PDEBUG ("send media succeed.\n");
}

void sendMedia (struct Session *p, struct Channel *pc)
{
	int i;
	struct LiveChannelInfo *pcinfo = pc->pcinfo;
	if (pcinfo == NULL || pcinfo->media == NULL) return;
	for (i=0; i<pcinfo->cur_channel; i++)
		sendHitMedia (p, pc, i, pcinfo->media[i].start, 1);
}

#ifdef __TEST_MEDIA
main ()
{
	struct Channel ch;
	struct LiveChannelInfo lch;
	memset (&ch, 0, sizeof (ch));
	memset (&lch, 0, sizeof (lch));
	ch.pcinfo = &lch;
	addMedia (&ch, 0, 100, 10, "aaaaaaaaa");
	if (lch.media != NULL)
		assert (0);
	lch.cur_channel = 0, lch.max_channel = 2;
	lch.media = calloc (2, sizeof (struct MediaData));
	addMedia (&ch, 0, 100, 10, "aaaaaaaaa");
	if (lch.media == NULL || strcmp (lch.media[0].data, "aaaaaaaaa") != 0)
		assert (0);
	addMedia (&ch, 0, 100, 10, "bbbbbbbbb");
	if (lch.media == NULL || strcmp (lch.media[0].data, "aaaaaaaaa") != 0
			|| strcmp (lch.media[1].data, "bbbbbbbbb") != 0)
		assert (0);
	freeMedia (&ch);
}
#endif
